package ${map.basePackage}.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.rulian.base.common.service.BaseService;
import cn.rulian.base.common.util.Num;
import cn.rulian.base.common.util.xx;
import cn.rulian.base.common.vo.Result;
import ${curd.boPath?substring(0,curd.boPath?last_index_of("."))}.*;
import ${map.basePackage}.dao.${map.boName}Dao${temp};
import ${map.basePackage}.vo.${map.boName}Footer;
import ${map.basePackage}.vo.${map.boName}Vo;

/**
 * ${curd.name}Service
 */
@Service
@Transactional(readOnly = true)
public class ${map.boName}Service${temp} extends BaseService<${map.boName}>
{

	// private final Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	EntityManager em;

	@Autowired
	private ${map.boName}Dao${temp} dao;

	@Override
	public ${map.boName}Dao${temp} getDao()
	{
		return dao;
	}
		
	/**
	 * 查询
	 */
	public Result query(final ${map.boName}Vo vo)
	{
		Sort sort = new Sort("desc".equals(vo.getOrder())?Direction.DESC:Direction.ASC, vo.getSort()); // 排序
		Pageable pageable = new PageRequest(vo.getPage() - 1, vo.getRows(), sort); // 分页查询条件

		//动态查询对象
		Specification<${map.boName}> specification = new Specification<${map.boName}>()
		{
			@Override
			public Predicate toPredicate(Root<${map.boName}> root, CriteriaQuery<?> cq, CriteriaBuilder cb)
			{
				return buildPredicate(root, cb, vo);
			}
		};

		// 查询
		Page<${map.boName}> page = dao.findAll(specification, pageable);
		Result result = Result.getResult(page);

	<#assign x=0 /> <#-- 用于判断是否有合计  -->
	<#list sumFields as item>
		<#assign x=1 />
    </#list>

	<#if x==1>
		//构建合计项
		List<${map.boName}Footer> footer = new ArrayList<>();
		//(1)标题
		${map.boName}Footer title = new ${map.boName}Footer();

	<#list sumFields as item>
		title.set${item.fieldName?cap_first}("${item.showName!item.fieldName}");
    </#list>
		
		footer.add(title);

		//(2)本页合计
		List<${map.boName}> ls = page.getContent();
		footer.add(this.getOnePageSum(ls));
		
		//(3)所有符合条件的合计项
		footer.add(this.getAllSum(vo));
		result.setFooter(footer);
	</#if>
		return result;
	}
	

	/**
	 * 构建查询条件
	 */
	private Predicate buildPredicate(Root<${map.boName}> root, CriteriaBuilder cb, ${map.boName}Vo vo)
	{
		List<Predicate> predicates = new ArrayList<Predicate>();

	<#list queryFields as item>
		<#if item.fieldType == "java.lang.String">
		//${item.showName!item.fieldName}
		String ${item.fieldName} = vo.get${item.fieldName?cap_first}();
		if(!xx.isEmpty(${item.fieldName}))
		{
			predicates.add(cb.like(root.get(${map.boName}_.${item.fieldName}), "%" + ${item.fieldName} + "%"));
		}

		<#elseif  item.otherBo>	
		// ${item.showName!item.fieldName} ID
		String ${item.fieldName}Id = vo.get${item.fieldName?cap_first}Id();	
		if(!xx.isEmpty(${item.fieldName}Id))
		{
			long num = xx.toLong(${item.fieldName}Id);
			predicates.add(cb.equal(root.get(${map.boName}_.${item.fieldName}).get(${item.fieldType?substring(item.fieldType?last_index_of(".")+1)}_.id), num));
		}

		<#elseif item.fieldType == "java.util.Date">
		// ${item.showName!item.fieldName}
		String ${item.fieldName}_start = vo.get${item.fieldName?cap_first}_start();	//开始时间
		String ${item.fieldName}_end = vo.get${item.fieldName?cap_first}_end();	//结束时间
		if(!xx.isEmpty(${item.fieldName}_start))
		{
			Date date = xx.toDate(${item.fieldName}_start);
			predicates.add(cb.greaterThanOrEqualTo(root.get(${map.boName}_.${item.fieldName}), date));

		}

		// 结束时间
		if(!xx.isEmpty(${item.fieldName}_end))
		{
			Date date = xx.toTime(${item.fieldName}_end + " 23:59:59");
			predicates.add(cb.lessThanOrEqualTo(root.get(${map.boName}_.${item.fieldName}), date));
		}

		</#if>
    </#list>

		return cb.and(predicates.toArray(new Predicate[predicates.size()]));
	}

<#if x==1>

	/**
	 * 汇总一页数据的合计信息
	 * @param ls
	 * @return
	 */
	private ${map.boName}Footer getOnePageSum(List<${map.boName}> ls)
	{
		${map.boName}Footer onePageSum = new ${map.boName}Footer();

	<#list sumFields as item>
		<#if item.fieldType == "java.lang.Integer" || item.fieldType == "java.lang.Short" || item.fieldType == "java.lang.Long">
		long ${item.fieldName} = 0; // ${item.showName!item.fieldName}
			
		<#elseif item.fieldType == "java.lang.Double" || item.fieldType == "java.lang.Float">
		double ${item.fieldName} = 0; // ${item.showName!item.fieldName}
		</#if>
    </#list>
		
		for(${map.boName} bo:ls)
		{
	<#list sumFields as item>
			if(bo.get${item.fieldName?cap_first}()!=null)
			{
		<#if item.fieldType == "java.lang.Integer" || item.fieldType == "java.lang.Short" || item.fieldType == "java.lang.Long">
				${item.fieldName} += bo.get${item.fieldName?cap_first}();
		<#elseif item.fieldType == "java.lang.Double" || item.fieldType == "java.lang.Float">
				${item.fieldName} = Num.add(${item.fieldName}, bo.get${item.fieldName?cap_first}());
		</#if>
			}
    </#list>
			
		}

	<#list sumFields as item>
		<#if item.fieldType == "java.lang.Integer" || item.fieldType == "java.lang.Short" || item.fieldType == "java.lang.Long">
		onePageSum.set${item.fieldName?cap_first}(${item.fieldName} + "");
		<#elseif item.fieldType == "java.lang.Double" || item.fieldType == "java.lang.Float">
		onePageSum.set${item.fieldName?cap_first}(Num.format(${item.fieldName}));
		</#if>
    </#list>

	<#list listFields as item>
		<#if item.sumTitle>
		onePageSum.set${item.fieldName?cap_first}("本页合计");
		</#if>
    </#list>
		//onePageSum.setHobby("本页合计");
		
		return onePageSum;
	}

	/**
	 * 获取所有符合条件的数据合计
	 */
	private ${map.boName}Footer getAllSum(${map.boName}Vo vo)
	{
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery();

		// from
		Root<${map.boName}> root = cq.from(${map.boName}.class);

		// where
		cq.where(this.buildPredicate(root, cb, vo));

		// 合计项
		cq.multiselect(
	<#assign k=0 />
	<#list sumFields as item>
		<#assign k=k+1 />
		<#if (k gt 1)>,</#if>cb.sum(root.get(${map.boName}_.${item.fieldName})).alias("${item.fieldName}")
    </#list>
				);
		
		// 查询
		List<Tuple> rows = em.createQuery(cq).getResultList();
		Tuple tuple = rows.get(0);
		${map.boName}Footer all = new ${map.boName}Footer();

	<#list sumFields as item>
		<#if item.fieldType == "java.lang.Integer" || item.fieldType == "java.lang.Short" || item.fieldType == "java.lang.Long">

		Long ${item.fieldName} = tuple.get("${item.fieldName}", Long.class); // 整数1
		all.set${item.fieldName?cap_first}(${item.fieldName}==null ? "0" : ${item.fieldName}.toString());

		<#elseif item.fieldType == "java.lang.Double" || item.fieldType == "java.lang.Float">

		Double ${item.fieldName} = tuple.get("${item.fieldName}", Double.class); // 实数2
		all.set${item.fieldName?cap_first}(${item.fieldName}==null ? "0" : Num.format(${item.fieldName}));

		</#if>
    </#list>

	<#list listFields as item>
		<#if item.sumTitle>
		all.set${item.fieldName?cap_first}("总合计");
		</#if>
    </#list>

		return all;
	}

</#if>
	
	/**
	 * 查询 Excel数据（不分页）
	 */
	public List<${map.boName}> QueryExcelData(final ${map.boName}Vo vo)
	{
		Sort sort = new Sort("desc".equals(vo.getOrder())?Direction.DESC:Direction.ASC, vo.getSort()); // 排序
		//动态查询对象
		Specification<${map.boName}> specification = new Specification<${map.boName}>()
		{
			@Override
			public Predicate toPredicate(Root<${map.boName}> root, CriteriaQuery<?> cq, CriteriaBuilder cb)
			{
				return buildPredicate(root, cb, vo);
			}
		};

		// 查询
		List<${map.boName}> list = dao.findAll(specification, sort);
		return list;
	}


}
